package com.webhiker.enigma2.api;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Logger;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;

import com.webhiker.dreambox.api.Utils;


public class Enigma2API {
	private Logger log = Logger.getAnonymousLogger();

	/** The password. */
	private String host, username, password;

	/** The port. */
	private int port;

	/**
	 * Instantiates a new dreambox api.
	 * 
	 * @param host the host
	 * @param port the port
	 * @param username the username
	 * @param password the password
	 */
	public Enigma2API(String host, int port, String username, String password) {
		setHost(host);
		setPort(port);
		setUsername(username);
		setPassword(password);
	}

	/**
	 * Gets the host.
	 * 
	 * @return the host
	 */
	public String getHost() {
		return host;
	}

	/**
	 * Sets the host.
	 * 
	 * @param host the new host
	 */
	public void setHost(String host) {
		this.host = host;
	}

	/**
	 * Gets the username.
	 * 
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * Sets the username.
	 * 
	 * @param username the new username
	 */
	public void setUsername(String username) {
		this.username = username;
		Authenticator.setDefault(new Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication (getUsername(), getPassword().toCharArray());
			}
		});
	}

	/**
	 * Gets the password.
	 * 
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * Sets the password.
	 * 
	 * @param password the new password
	 */
	public void setPassword(String password) {
		this.password = password;
		Authenticator.setDefault(new Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication (getUsername(), getPassword().toCharArray());
			}
		});
	}

	/**
	 * Gets the port.
	 * 
	 * @return the port
	 */
	public int getPort() {
		return port;
	}

	/**
	 * Sets the port.
	 * 
	 * @param port the new port
	 */
	public void setPort(int port) {
		this.port = port;
	}

	/**
	 * Gets the base.
	 * 
	 * @return the base
	 */
	private String getBase() {
		return "http://"+getHost()+":"+getPort();
	}

	/**
	 * Gets the connection.
	 * 
	 * @param location the location
	 * 
	 * @return the connection
	 * 
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	private URLConnection getConnection(String location) throws IOException {
		// Need to work with URLConnection to set request property
		URL url = new URL(getBase()+location);
		URLConnection uc = url.openConnection();
		return uc;
	}

	public JSONObject getAbout() throws IOException, JSONException {
		String location = "/web/about";
		URLConnection urlConn = getConnection(location);
		Utils.validateResponse(urlConn);
		final char[] buffer = new char[0x10000];
		StringBuilder out = new StringBuilder();
		Reader in = new InputStreamReader(urlConn.getInputStream(), "UTF-8");
		int read;
		do {
			read = in.read(buffer, 0, buffer.length);
			if (read>0) {
				out.append(buffer, 0, read);
			}
		} while (read>=0);
		in.close();
		return XML.toJSONObject(out.toString());
	}

	public Signal getSignal() throws IOException, JSONException {
		String location = "/web/signal";
		URLConnection urlConn = getConnection(location);
		Utils.validateResponse(urlConn);
		final char[] buffer = new char[0x10000];
		StringBuilder out = new StringBuilder();
		Reader in = new InputStreamReader(urlConn.getInputStream(), "UTF-8");
		int read;
		do {
			read = in.read(buffer, 0, buffer.length);
			if (read>0) {
				out.append(buffer, 0, read);
			}
		} while (read>=0);
		in.close();
		return new Signal(XML.toJSONObject(out.toString()));
	}


}
